﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using System.Threading;
using Services;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.IO.IsolatedStorage;
using Utilities;
using System.Text;
using System.Security.Cryptography;
using Services.Menu;

namespace TrenitaliaWP7
{
    public class OptionsState
    {
        public ArrayList<String> stations1;
        public ArrayList<String> stations2;
        public int order;
        public bool allowRunOffScreen;
        public int autoUpdateMode;
        public bool showCompletePaths;
        public bool vibration;
        public bool feedback;
        public bool AllowGPS;
        public bool suggestionKeyboard;
        public bool FirstUse;
        public bool showAlwaysTimes;
        public bool showAllSolutions;
        //public bool isCracked;
        public OptionsState()
        {
            stations1 = new ArrayList<string>();
            stations2 = new ArrayList<string>();
            order = 0;
            allowRunOffScreen = true;
            showCompletePaths = true;
            vibration = false;
            feedback = true;
            AllowGPS = false;
            FirstUse = true;
            showAlwaysTimes = true;
            showAllSolutions = false;
            suggestionKeyboard = true;
            //isCracked = false;
        }
        public void AddStations(string from, string to)
        {
            stations1.Remove(from);
            if (to != from && from != "")
                stations1.Remove(to);
            stations2.Remove(from);
            if (to != from && to != "")
                stations2.Remove(to);
            var newList = new ArrayList<String>();

            if (from != "")
                newList.Add(from);
            if (to != from && to != "")
                newList.Add(to);
            for (int i = 0; i < stations1.Count; i++)
                newList.Add(stations1[i]);
            stations1 = newList;


            newList = new ArrayList<String>();
            string a = String.Compare(from, to) > 0 ? from : to;
            string b = String.Compare(from, to) < 0 ? from : to;
            if (from == to)
                b = "";
            for (int i = 0; i < stations2.Count; i++)
            {
                if (a != "" && string.Compare(a, stations2[i]) < 0)
                {
                    newList.Add(a);
                    a = "";
                    i--;
                }
                else if (b != "" && string.Compare(b, stations2[i]) < 0)
                {
                    newList.Add(b);
                    b = "";
                    i--;
                }
                else
                    newList.Add(stations2[i]);
            }
            if (a != "")
                newList.Add(a);
            if (b != "")
                newList.Add(b);
            stations2 = newList;
            //var ordered = stations.OrderBy(s => s).ToList();
            //stations.Clear();
            //foreach(var s in ordered)
            //    stations.Add(s);


        }
        public void RemoveStation(string old)
        {
            stations1.Remove(old);
            stations2.Remove(old);
        }
    }

    public static class Storage
    {
        private static Func<StreamReader, OptionsState> read_options_state = reader =>
        {
            OptionsState os = new OptionsState();

            var s = reader.ReadToEnd();
            var t = s.Split(new[] { ',' });
            os.order = Int16.Parse(t[0]);
            os.allowRunOffScreen = bool.Parse(t[1]);
            os.autoUpdateMode = Int16.Parse(t[2]);
            os.showCompletePaths = bool.Parse(t[3]);
            os.vibration = bool.Parse(t[4]);
            os.feedback = bool.Parse(t[5]);

            os.AllowGPS = bool.Parse(t[6]) && OptionsMenu.ESABLE_GPS;
            os.FirstUse = bool.Parse(t[7]) && OptionsMenu.ESABLE_GPS;
            os.showAlwaysTimes = bool.Parse(t[8]);
            os.showAllSolutions = bool.Parse(t[9]);
            os.suggestionKeyboard = bool.Parse(t[10]);
            //os.stations1 = read_stations(t[7]);
            //os.stations2 = read_stations(t[8]);
            //var r = t[7].Split(new[] { ';' });
            //for (int i = 0; i < r.Length; i++)
            //{
            //    if (r[i] != "")
            //        os.stations1.Add(r[i]);
            //}
            //r = t[8].Split(new[] { ';' });
            //for (int i = 0; i < r.Length; i++)
            //{
            //    if (r[i] != "")
            //        os.stations2.Add(r[i]);
            //}
            return os;

        };
        private static Func<StreamReader, OptionsState, OptionsState> read_stations_lists = (reader, os) =>
        {
            var s = reader.ReadToEnd();
            var t = s.Split(new[] { ',' });

            os.stations1 = read_stations(t[0]);
            os.stations2 = read_stations(t[1]);
            return os;
        };
        private static Func<String, ArrayList<string>> read_stations = reader =>
        {
            OptionsState os = new OptionsState();
            ArrayList<string> result = new ArrayList<String>();
            var r = reader.Split(new[] { ';' });
            for (int i = 0; i < r.Length; i++)
            {
                if (r[i] != "")
                    result.Add(r[i]);
            }
            //r = t[7].Split(new[] { ';' });
            //for (int i = 0; i < r.Length; i++)
            //{
            //    if (r[i] != "")
            //        result.Add(r[i]);
            //}
            return result;

        };

        private static Action<StreamWriter, OptionsState> write_options_state = (writer, entry) =>
        {
            var s = "" + entry.order + "," + entry.allowRunOffScreen + "," + entry.autoUpdateMode + "," +
                entry.showCompletePaths + "," + entry.vibration + "," + entry.feedback + "," + entry.AllowGPS + "," + entry.FirstUse + "," +
                entry.showAlwaysTimes + "," + entry.showAllSolutions + "," + entry.suggestionKeyboard;
            //s += ",";
            //s += write_stations(entry.stations1);
            //s += ",";
            //s+=write_stations(entry.stations2);
            //for (int i = 0; i < entry.stations1.Count - 1; i++)
            //    if (entry.stations1[i] != "")
            //        s += entry.stations1[i] + ";";
            //if (entry.stations1.Count >= 1 && entry.stations1[entry.stations1.Count - 1] != "")
            //    s += entry.stations1[entry.stations1.Count - 1];
            //s += ",";
            //for (int i = 0; i < entry.stations2.Count - 1; i++)
            //    if (entry.stations2[i] != "")
            //        s += entry.stations2[i] + ";";
            //if (entry.stations2.Count >= 1 && entry.stations2[entry.stations2.Count - 1] != "")
            //    s += entry.stations2[entry.stations2.Count - 1];
            writer.Write(s);
        };


        private static Action<StreamWriter, ArrayList<string>, ArrayList<string>> write_stations = (writer, stations1, stations2) =>
        {
            var s = "";
            for (int i = 0; i < stations1.Count - 1; i++)
                if (stations1[i] != "")
                    s += stations1[i] + ";";
            if (stations1.Count >= 1 && stations1[stations1.Count - 1] != "")
                s += stations1[stations1.Count - 1];

            s += ",";

            for (int i = 0; i < stations2.Count - 1; i++)
                if (stations2[i] != "")
                    s += stations2[i] + ";";
            if (stations2.Count >= 1 && stations2[stations2.Count - 1] != "")
                s += stations2[stations2.Count - 1];


            writer.Write(s);
        };


        public static void SaveOptionsState(OptionsState entry)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("options.txt");
                using (var streamFile = appStorage.OpenFile("options.txt", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                    write_options_state(writer, entry);

                appStorage.DeleteFile("stations.txt");
                using (var streamFile = appStorage.OpenFile("stations.txt", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                    write_stations(writer, entry.stations1, entry.stations2);
            }
        }

        public static void SaveOnlyOptionsState(OptionsState entry)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("options.txt");
                using (var streamFile = appStorage.OpenFile("options.txt", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                    write_options_state(writer, entry);
            }
        }


        public static OptionsState ResetOptionsState()
        {
            var os = new OptionsState();
            //SaveOnlyOptionsState(os);
            return os;
        }

        public static OptionsState GetOptionsState()
        {
            OptionsState os = new OptionsState();
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("options.txt", FileMode.OpenOrCreate))
                {
                    try
                    {
                        using (var reader = new StreamReader(streamFile))
                            os = read_options_state(reader);
                    }
                    catch (Exception) { os = ResetOptionsState(); }
                }

                using (var streamFile = appStorage.OpenFile("stations.txt", FileMode.OpenOrCreate))
                {
                    try
                    {
                        using (var reader = new StreamReader(streamFile))
                            return read_stations_lists(reader, os);
                    }
                    catch (Exception) { return os; }
                }
            }

        }

        #region Crack




        public static Byte[] CreateMD5Hash(string input)
        {
            var hashalg = new SHA256Managed();
            var h = hashalg.ComputeHash(Encoding.UTF8.GetBytes(input));
            return h;
        }

        public static bool CheckSavedCrack()
        {
            Byte[] saved = GetCrackFile(true);
            Byte[] hash = StateManager.Crack_Hash;
            if (saved.Length != hash.Length)
                return false;
            for (int i = 0; i < saved.Length; i++)
                if (saved[i] != hash[i])
                    return false;
            return true;

        }

        public static bool CheckCrack(Byte[] hash)
        {
            Byte[] saved = GetCrackFile(false);
            if (saved.Length != hash.Length)
                return false;
            for (int i = 0; i < saved.Length; i++)
                if (saved[i] != hash[i])
                    return false;
            SaveCrackFile(saved);
            return true;
        }


        private static Func<StreamReader, Byte[]> read_crack_file = reader =>
        {


            var s = reader.ReadToEnd();
            var a = s.Split(new[] { ';' });
            Byte[] h = new Byte[a.Length];
            for (int i = 0; i < a.Length; i++)
                h[i] = Byte.Parse(a[i]);
            return h;

        };

        private static Action<StreamWriter, Byte[]> write_crack_file = (writer, h) =>
        {
            var s = "";
            for (int i = 0; i < h.Length - 1; i++)
                s += h[i] + ";";
            if (h.Length > 0)
                s += h[h.Length - 1];
            writer.Write(s);
        };

        public static void DeleteCrackFile()
        {
            try
            {
                using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    appStorage.DeleteFile("crack.txt");
                }
            }
            catch (Exception e)
            {
                e.ToString();
            }
        }

        public static void SaveCrackFile(Byte[] h)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("crack.txt");
                using (var streamFile = appStorage.OpenFile("crack.txt", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                    write_crack_file(writer, h);
            }
        }

        public static Byte[] GetCrackFile(bool initial_check)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("crack.txt", FileMode.OpenOrCreate))
                {
                    try
                    {
                        using (var reader = new StreamReader(streamFile))
                            return read_crack_file(reader);
                    }
                    catch (Exception)
                    {
                        //SaveCrackFile(StateManager.Crack_Hash);
                        if (initial_check)
                            return new Byte[0];
                        else
                            return StateManager.Crack_Hash;
                    }
                }
            }
        }






        #endregion

        #region favorites
        public static Favorites LoadFavorites()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("favorites.xml", FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(Favorites));
                        using (var reader = new StreamReader(streamFile))
                            return serializer.Deserialize(reader) as Favorites;
                    }
                    catch (Exception) { return new Favorites(); }
                }
            }
        }

        public static void DeleteFavorites()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("favorites.xml");
            }
        }

        public static void SaveFavorites(Favorites state)
        {
            try
            {
                using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    appStorage.DeleteFile("favorites.xml");
                    using (var streamFile = appStorage.OpenFile("favorites.xml", FileMode.OpenOrCreate))
                    using (var writer = new StreamWriter(streamFile))
                    //write_options_state(writer, entry);
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(Favorites));
                        serializer.Serialize(writer, state);
                    }
                }
            }
            catch (Exception e)
            {
                e.ToString();
            }
        }
        #endregion

        #region saved results
        public static List<SavedResults> LoadSavedResults()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("SavedResults.xml", FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(List<SavedResults>));
                        using (var reader = new StreamReader(streamFile))
                            return serializer.Deserialize(reader) as List<SavedResults>;
                    }
                    catch (Exception) { return DeleteSavedResults(); }
                }
            }
        }

        public static List<SavedResults> DeleteSavedResults()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("SavedResults.xml");
                return new List<SavedResults>();
            }
        }

        public static void SaveSavedResults(List<SavedResults> state)
        {
            try
            {
                using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    appStorage.DeleteFile("SavedResults.xml");
                    using (var streamFile = appStorage.OpenFile("SavedResults.xml", FileMode.OpenOrCreate))
                    using (var writer = new StreamWriter(streamFile))
                    //write_options_state(writer, entry);
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(List<SavedResults>));
                        serializer.Serialize(writer, state);
                    }
                }
            }
            catch (Exception e)
            {
                e.ToString();
            }
        }
        #endregion

        #region utilizations
        private static Func<StreamReader, int> read_utilizations = reader =>
        {

            var s = reader.ReadToEnd();
            var occ = Int16.Parse(s);


            return occ;
        };


        private static Action<StreamWriter, int> write_utilizations = (writer, occ) =>
        {
            var s = "" + occ;

            writer.Write(s);
        };



        public static void SaveUtilizations(int utilizations)
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile("utilizations.txt");
                using (var streamFile = appStorage.OpenFile("utilizations.txt", FileMode.OpenOrCreate))
                using (var writer = new StreamWriter(streamFile))
                    write_utilizations(writer, utilizations);
            }
        }



        public static void DeleteUtilizations()
        {
            var appStorage = IsolatedStorageFile.GetUserStoreForApplication();
            appStorage.DeleteFile("utilizations.txt");
        }

        public static int LoadUtilizations()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile("utilizations.txt", FileMode.OpenOrCreate))
                {
                    try
                    {
                        using (var reader = new StreamReader(streamFile))
                            return read_utilizations(reader);
                    }
                    catch (Exception)
                    {
                        appStorage.DeleteFile("utilizations.txt");
                        return 0;
                    }
                }


            }

        }
        #endregion


        #region shortcuts
        static string shortcuts_file = "shortcuts.xml";
        public static List<ShortCut> LoadShortCuts()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (var streamFile = appStorage.OpenFile(shortcuts_file, FileMode.OpenOrCreate))
                {
                    try
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(List<ShortCut>));
                        using (var reader = new StreamReader(streamFile))
                            return serializer.Deserialize(reader) as List<ShortCut>;
                    }
                    catch (Exception) { return new List<ShortCut>(); }
                }
            }
        }

        public static void DeleteShortCuts()
        {
            using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                appStorage.DeleteFile(shortcuts_file);
            }
        }

        public static void SaveShortCuts(List<ShortCut> state)
        {
            try
            {
                using (var appStorage = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    appStorage.DeleteFile(shortcuts_file);
                    using (var streamFile = appStorage.OpenFile(shortcuts_file, FileMode.OpenOrCreate))
                    using (var writer = new StreamWriter(streamFile))
                    //write_options_state(writer, entry);
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(List<ShortCut>));
                        serializer.Serialize(writer, state);
                    }
                }
            }
            catch (Exception e)
            {
                e.ToString();
            }
        }

        public static void BuildShortCuts(List<ShortCut> shortCuts, List<Station> stations)
        {
            shortCuts.Clear();
            List<ShortCut> list = new List<ShortCut>();
#region Province
            
            list.Add(new ShortCut("Agrigento","AG",true));
list.Add(new ShortCut("Alessandria","AL",true));
list.Add(new ShortCut("Ancona","AN",true));
list.Add(new ShortCut("Aosta","AO",true));
list.Add(new ShortCut("Arezzo","AR",true));
list.Add(new ShortCut("AscoliPiceno","AP",true));
list.Add(new ShortCut("Asti","AT",true));
list.Add(new ShortCut("Avellino","AV",true));
list.Add(new ShortCut("Bari","BA",true));
list.Add(new ShortCut("Barletta-Andria-Trani","BT",true));
list.Add(new ShortCut("Belluno","BL",true));
list.Add(new ShortCut("Benevento","BN",true));
list.Add(new ShortCut("Bergamo","BG",true));
list.Add(new ShortCut("Biella","BI",true));
list.Add(new ShortCut("Bologna","BO",true));
list.Add(new ShortCut("Bolzano","BZ",true));
list.Add(new ShortCut("Brescia","BS",true));
list.Add(new ShortCut("Brindisi","BR",true));
list.Add(new ShortCut("Cagliari","CA",true));
list.Add(new ShortCut("Caltanissetta","CL",true));
list.Add(new ShortCut("Campobasso","CB",true));
list.Add(new ShortCut("Carbonia-Iglesias","CI",true));
list.Add(new ShortCut("Caserta","CE",true));
list.Add(new ShortCut("Catania","CT",true));
list.Add(new ShortCut("Catanzaro","CZ",true));
list.Add(new ShortCut("Chieti","CH",true));
list.Add(new ShortCut("Como","CO",true));
list.Add(new ShortCut("Cosenza","CS",true));
list.Add(new ShortCut("Cremona","CR",true));
list.Add(new ShortCut("Crotone","KR",true));
list.Add(new ShortCut("Cuneo","CN",true));
list.Add(new ShortCut("Enna","EN",true));
list.Add(new ShortCut("Fermo","FM",true));
list.Add(new ShortCut("Ferrara","FE",true));
list.Add(new ShortCut("Firenze","FI",true));
list.Add(new ShortCut("Foggia","FG",true));
list.Add(new ShortCut("Forlì-Cesena","FC",true));
list.Add(new ShortCut("Frosinone","FR",true));
list.Add(new ShortCut("Genova","GE",true));
list.Add(new ShortCut("Gorizia","GO",true));
list.Add(new ShortCut("Grosseto","GR",true));
list.Add(new ShortCut("Imperia","IM",true));
list.Add(new ShortCut("Isernia","IS",true));
list.Add(new ShortCut("LaSpezia","SP",true));
list.Add(new ShortCut("L'Aquila","AQ",true));
list.Add(new ShortCut("Latina","LT",true));
list.Add(new ShortCut("Lecce","LE",true));
list.Add(new ShortCut("Lecco","LC",true));
list.Add(new ShortCut("Livorno","LI",true));
list.Add(new ShortCut("Lodi","LO",true));
list.Add(new ShortCut("Lucca","LU",true));
list.Add(new ShortCut("Macerata","MC",true));
list.Add(new ShortCut("Mantova","MN",true));
list.Add(new ShortCut("Massa-Carrara","MS",true));
list.Add(new ShortCut("Matera","MT",true));
list.Add(new ShortCut("Messina","ME",true));
list.Add(new ShortCut("Milano","MI",true));
list.Add(new ShortCut("Modena","MO",true));
list.Add(new ShortCut("MonzaedellaBrianza","MB",true));
list.Add(new ShortCut("Napoli","NA",true));
list.Add(new ShortCut("Novara","NO",true));
list.Add(new ShortCut("Nuoro","NU",true));
list.Add(new ShortCut("Olbia-Tempio","OT",true));
list.Add(new ShortCut("Oristano","OR",true));
list.Add(new ShortCut("Padova","PD",true));
list.Add(new ShortCut("Palermo","PA",true));
list.Add(new ShortCut("Parma","PR",true));
list.Add(new ShortCut("Pavia","PV",true));
list.Add(new ShortCut("Perugia","PG",true));
list.Add(new ShortCut("PesaroeUrbino","PU",true));
list.Add(new ShortCut("Pescara","PE",true));
list.Add(new ShortCut("Piacenza","PC",true));
list.Add(new ShortCut("Pisa","PI",true));
list.Add(new ShortCut("Pistoia","PT",true));
list.Add(new ShortCut("Pordenone","PN",true));
list.Add(new ShortCut("Potenza","PZ",true));
list.Add(new ShortCut("Prato","PO",true));
list.Add(new ShortCut("Ragusa","RG",true));
list.Add(new ShortCut("Ravenna","RA",true));
list.Add(new ShortCut("ReggioCalabria","RC",true));
list.Add(new ShortCut("ReggioEmilia","RE",true));
list.Add(new ShortCut("Rieti","RI",true));
list.Add(new ShortCut("Rimini","RN",true));
list.Add(new ShortCut("Roma","RM",true));
list.Add(new ShortCut("Rovigo","RO",true));
list.Add(new ShortCut("Salerno","SA",true));
list.Add(new ShortCut("MedioCampidano","VS",true));
list.Add(new ShortCut("Sassari","SS",true));
list.Add(new ShortCut("Savona","SV",true));
list.Add(new ShortCut("Siena","SI",true));
list.Add(new ShortCut("Siracusa","SR",true));
list.Add(new ShortCut("Sondrio","SO",true));
list.Add(new ShortCut("Taranto","TA",true));
list.Add(new ShortCut("Teramo","TE",true));
list.Add(new ShortCut("Terni","TR",true));
list.Add(new ShortCut("Torino","TO",true));
list.Add(new ShortCut("Ogliastra","OG",true));
list.Add(new ShortCut("Trapani","TP",true));
list.Add(new ShortCut("Trento","TN",true));
list.Add(new ShortCut("Treviso","TV",true));
list.Add(new ShortCut("Trieste","TS",true));
list.Add(new ShortCut("Udine","UD",true));
list.Add(new ShortCut("Varese","VA",true));
list.Add(new ShortCut("Venezia","VE",true));
list.Add(new ShortCut("Verbano-Cusio-Ossola","VB",true));
list.Add(new ShortCut("Vercelli","VC",true));
list.Add(new ShortCut("Verona","VR",true));
list.Add(new ShortCut("ViboValentia","VV",true));
list.Add(new ShortCut("Vicenza","VI",true));
list.Add(new ShortCut("Viterbo","VT",true));

#endregion

            for (int i = 0; i < stations.Count; i++)
            {
                for(int j=0;j<list.Count;j++)
                    if (stations[i].name.ToLower().Contains(list[j].value.ToLower()))
                    {
                        if(i>0 && stations[i].name!=stations[i-1].name)
                            shortCuts.Add(new ShortCut(list[j].shortcut, stations[i].name));
                    }
            }

            SaveShortCuts(shortCuts);
            return;
        }
        #endregion

    }
}
